package 作用域相关;


import 抽象语法树节点.抽象语法树;

public class 符号表 {

    public final 全局作用域 全局作用域 = new 全局作用域();

    public 符号表() {
        初始化类型系统();
    }

    protected void 初始化类型系统() {
        全局作用域.定义((符号) 类型索引.逻辑型.类型);
        全局作用域.定义((符号) 类型索引.字符型.类型);
        全局作用域.定义((符号) 类型索引.整数型.类型);
        全局作用域.定义((符号) 类型索引.浮点型.类型);
        全局作用域.定义((符号) 类型索引.空.类型);
    }

    public String toString() {
        return 全局作用域.toString();
    }


    // bop (binary operator)
    public 类型 二元运算(抽象语法树 左, 抽象语法树 右) {
        return 左.求值类型;
    }

    // relop (relational operator)
    public 类型 关系运算(抽象语法树 左, 抽象语法树 右) {
        return 类型索引.逻辑型.类型;
    }

    // eqop (equality operator)
    public 类型 匹值运算(抽象语法树 左, 抽象语法树 右) {
        return 类型索引.逻辑型.类型;
    }

    // uminus
    public 类型 取负(抽象语法树 树) {
        return 树.求值类型;
    }

    // unot
    public 类型 取反(抽象语法树 树) {
        return 类型索引.逻辑型.类型;
    }

    public 类型 数组访问(抽象语法树 数组, 抽象语法树 下标) {
        var 符号 = (变量符号) 数组.作用域.解析(数组.token.getText());
        数组.符号 = 符号;
        return ((数组类型) 符号.类型).元素类型;
    }

    public 类型 方法调用(抽象语法树 方法, 抽象语法树 参数) {
        var 符号 = (方法符号) 方法.作用域.解析(方法.token.getText());
        方法.符号 = 符号;
        return 符号.类型;
    }

    public 类型 成员访问(抽象语法树 对象, String 成员名) {
        var 作用域 = (结构体符号) 对象.求值类型;
        var 符号 = 作用域.解析成员(成员名);
        return 符号.类型;
    }


    public 方法符号 取方法符号(作用域 作用域) {
        do {
            if (作用域 instanceof 方法符号) {
                return (方法符号) 作用域;
            }

            作用域 = 作用域.取外围作用域();
        }
        while (作用域 != null);
        return null;
    }
}
